package lg.minecraft.plugin.pokemonmenu;

import com.cobblemon.mod.common.api.Priority;
import com.cobblemon.mod.common.api.events.CobblemonEvents;
import com.cobblemon.mod.common.api.reactive.Observable;
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
import com.cobblemon.mod.common.pokemon.Pokemon;
import lg.minecraft.plugin.cobblemoncore.util.CobblemonEventHandler;
import lg.minecraft.plugin.library.LGPlugin;
import lg.minecraft.plugin.pokemonmenu.command.*;
import lg.minecraft.plugin.pokemonmenu.config.GuiItem;
import lg.minecraft.plugin.pokemonmenu.config.MainConfig;
import lg.minecraft.plugin.pokemonmenu.config.Message;
import lg.minecraft.plugin.pokemonmenu.gui.PInventory;
import lg.minecraft.plugin.pokemonmenu.listener.CobblemonEvent;
import lg.minecraft.plugin.pokemonmenu.listener.PlayerEvent;
import lg.minecraft.plugin.pokemonmenu.manager.DisplayPokemonManger;
import lg.minecraft.plugin.pokemonmenu.manager.PokemonDataManager;
import lg.minecraft.plugin.pokemonmenu.metrics.bukkit.Metrics;
import lg.minecraft.plugin.pokemonmenu.tasks.InventoryRealTimeUpdate;
import lg.minecraft.plugin.pokemonmenu.tasks.PokemonDisplayCleanupTask;
import lombok.Getter;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;

import java.util.function.Consumer;

/**
 * @author langle__
 * @version 1.0
 */
public final class LGPokemonMenu extends LGPlugin {

    @Getter private static LGPokemonMenu instance;

    @Getter private static MainConfig mainConfig;
    @Getter private static GuiItem guiItem;
    @Getter private static Message message;

    @Getter private static Economy economy;

    private static PokemonDisplayCleanupTask cleanupTask;
    private static InventoryRealTimeUpdate inventoryUpdate;

    @Override
    public void onEnable() {
        instance = this;
        mainConfig = new MainConfig();
        guiItem = new GuiItem();
        message = new Message();
        new InputCommand();
        MainCommand mainCommand = new MainCommand();
        mainCommand.registerSubCommand(new SubOpenCommand());
        mainCommand.registerSubCommand(new SubViewCommand());
        mainCommand.registerSubCommand(new SubReloadCommand());
        cleanupTask = new PokemonDisplayCleanupTask();
        cleanupTask.start();
        inventoryUpdate = new InventoryRealTimeUpdate();
        inventoryUpdate.canStart();
        loadSettings();
        Bukkit.getPluginManager().registerEvents(new PlayerEvent(), this);
        registerCobblemonEvent(CobblemonEvents.BATTLE_VICTORY, Priority.NORMAL, CobblemonEvent::onBattleVictory);
        registerCobblemonEvent(CobblemonEvents.BATTLE_FLED, Priority.NORMAL, CobblemonEvent::onBattleFled);
        if (!setupEconomy()) getLogger().info("没有找到 Vault 经济系统");
        Metrics metrics = new Metrics(this, 26101);
    }

    @Override
    public void onDisable() {
        if (cleanupTask != null) cleanupTask.stop();
        PokemonDataManager.INSTANCE.close();
    }

    @Override
    public void reloadConfig() {
        mainConfig.saveDefault();
        mainConfig.load();
        guiItem.saveDefault();
        guiItem.load();
        message.saveDefault();
        message.load();
        loadSettings();
    }

    public void loadSettings() {
        PokemonDataManager.INSTANCE.close();
        PokemonDataManager.INSTANCE.loadSettings();
        DisplayPokemonManger.INSTANCE.setCooldownMillis(mainConfig.getDisplayCooldown() * 1000);
        if (LGPokemonMenu.getMainConfig().isRealTimeUpdate()) {
            inventoryUpdate.start();
        } else {
            inventoryUpdate.stop();
        }
    }

    private boolean setupEconomy() {
        if (getServer().getPluginManager().getPlugin("Vault") == null) {
            return false;
        }
        RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
        if (rsp == null) {
            return false;
        }
        economy = rsp.getProvider();
        return true;
    }

    private <T> void registerCobblemonEvent(Observable<T> observable, Priority priority, Consumer<T> handler) {
        CobblemonEventHandler.registerCobblemonEvent(this, observable, priority, handler);
    }

    public static boolean canPartyBeHealed(PlayerPartyStore party) {
        for (Pokemon pokemon : party) if (pokemon != null && pokemon.canBeHealed()) return true;
        return false;
    }

    public static void addOpeningInventory(Player player, PInventory inventory) {
        if (!player.isOnline()) return;
        inventoryUpdate.addPlayer(player, inventory);
    }

    public static void removeOpeningInventory(Player player) {
        inventoryUpdate.removePlayer(player);
    }

}
